#ifndef _EPOLL_SOCKET_H_
#define _EPOLL_SOCKET_H_
/**********************************************************************************
  *Copyright 2020-05-06, pyfree
  *
  *File Name       : epoll_socket.h
  *File Mark       : 
  *Summary         : 
  *
  *Current Version : 1.00
  *Author          : pyfree
  *FinishDate      :
  *
  *Replace Version :
  *Author          :
  *FinishDate      :

 ***********************************************************************************/
#include <sys/socket.h>  
#include <sys/epoll.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <string>
#include <set>

#include "thread_py.h"
#include "queuedata.h"
#include "Mutex.h"

struct ItemCache
{
	ItemCache()
		: data(""),fd(-1)
	{
	};
	ItemCache(std::string data_)
		: data(data_),fd(-1)
	{
	};
	ItemCache(std::string data_,int fd_)
		: data(data_),fd(fd_)
	{
	};
	std::string data;
	int fd;
};

class epoll_socket : public Thread_py
{
public:
	epoll_socket();
	~epoll_socket();
	/**
	 * 打开服务侦听
	 * @param port {int} 侦听端口
	 * @param isblock_listen {bool} 是否阻塞
	 * @return {void} 
	 */
	bool open(int port, bool isblock_listen = false);

	int get_socketfd();
	/**
	 * 线程运行函数
	 * @return {char*} 
	 */
	int run();
	/**
	 * 指定fd发送字符串
	 * @param item {string} 字符内容
	 * @param fd {int} -1时,对所有fd发送
	 * @return {void} 
	 */
	void send(std::string item, int fd=-1);
	/**
	 * 获取客户端内容
	 * @param item {string&} 字符内容
	 * @param fd {int&} 	客户端fd
	 * @return {bool} 
	 */
	bool get(std::string &item,int &fd);
	/**
	 * 获取最新异常信息
	 * @return {char*} 
	 */
	char* get_errmsg();
	/**
	 * 设置读写数据时是否打印输出
	 * @param flag {bool} 	是否打印
	 * @return {char*} 
	 */
	void setPrintFlag(bool flag);
	/**
	 * 设置客户端事务是否阻塞
	 * @param flag {bool} 	是否阻塞
	 * @return {char*} 
	 */
	void setClientBlock(bool flag);
private:
	void add_event(int fd, int state);
	void del_event(int fd, int state);
	void mod_event(int fd, int state);
	void add_client(int fd);
	void del_client(int fd);

	void handle_events(struct epoll_event *events, int num);

	bool handle_accept();

	bool do_read(int fd);

	bool do_write(int fd);
private:
	bool running;
	bool print_flag;
	bool isblock_client;
	int socketfd;
	struct sockaddr_in servaddr;
	int epollfd;
	char err_msg[256];
	std::set<int> fds_client;
	PYMutex	fds_mutex;
	QueueData<ItemCache> buffer_read;
	QueueData<ItemCache> buffer_write;
};

#endif
